#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>

#include "star_types.h"

/**
 * @brief convert single line text into a starship struct
 *
 * @param line
 * @return Starship
 */
Starship convert_line_to_starship(char *line)
{
    Starship ship;
    char *start = line;
    char *next_spliter = strstr(start, "##");

    // replace ## into \0
    *next_spliter = '\0';
    // copy attribue
    strcpy(ship.Name, start);

    start = next_spliter + 2;
    next_spliter = strstr(start, "##");
    *next_spliter = '\0';
    sscanf(start, "%d", &ship.TopSpeed);

    start = next_spliter + 2;
    next_spliter = strstr(start, "##");
    *next_spliter = '\0';
    sscanf(start, "%d", &ship.ProcessingOptions);

    start = next_spliter + 2;
    next_spliter = strstr(start, "##");
    *next_spliter = '\0';
    strcpy(ship.DestinationName, start);

    return ship;
}

/**
 * @brief read starship file
 *
 * @param filename
 * @return a linked list of starship
 */
StarshipListNode *read_starship_file(const char *filename)
{
    // open file
    FILE *ship_file = fopen(filename, "r+");
    // create head pointer of the singly linked list
    StarshipListNode *starshipList = NULL;
    StarshipListNode *head = starshipList;

    // read file until it is end
    while (!feof(ship_file))
    {
        // create first node
        head = (StarshipListNode *)malloc(sizeof(StarshipListNode));
        char line[4 * 128];
        fgets(line, 4 * 128, ship_file);
        head->starship = convert_line_to_starship(line);
        // head insertion
        // add a star system into linked list
        head->next = starshipList;
        starshipList = head;
    }

    // testing output, not necessary
    
    StarshipListNode *p = starshipList;
    while (p != NULL)
    {
        // printf("Testing output：(starship)：%s %d %d %s \n", p->starship.Name, p->starship.TopSpeed, p->starship.ProcessingOptions, p->starship.DestinationName);
        p = p->next;
    }
    return starshipList;
    
}
/**
 * @brief read star system file
 *
 * @param filename
 * @return StarSystemListNode*
 */
StarSystemListNode *read_star_system_file(const char *filename)
{
    FILE *ship_system_file = fopen(filename, "r+");

    // create head pointer of the singly linked list
    StarSystemListNode *starSystemList = NULL;
    StarSystemListNode *head = starSystemList;

    // read file until it is end
    while (!feof(ship_system_file))
    {
        // create the first node of the singly linked list
        head = (StarSystemListNode *)malloc(sizeof(StarSystemListNode));

        char line_buf[4 * 128];
        fgets(line_buf, 4 * 128, ship_system_file);

        // replace the \n into string end mark
        // actually, i deleted \n
        *strstr(line_buf, "\n") = '\0';
        strcpy(head->starSystem.Name, line_buf);

        // read 4 lines from file
        for (int i = 0; i < 4; i++)
        {
            fgets(line_buf, 4 * 128, ship_system_file);

            // start of main attribute string
            char *main_attr = strstr(line_buf, ": \"") + 3;
            // replace the last quotation mark into string end mark
            // actually, i splitted the string and it's easy to use strcpy to copy attribute
            *strstr(main_attr, "\"") = '\0';

            // copy attribue
            if (strstr(line_buf, "constellation") != NULL)
            {
                strcpy(head->starSystem.Constellation, main_attr);
            }
            else if (strstr(line_buf, "description") != NULL)
            {
                strcpy(head->starSystem.Description, main_attr);
            }
            else if (strstr(line_buf, "mass") != NULL)
            {
                head->starSystem.Mass = atof(main_attr);
            }
            else if (strstr(line_buf, "temperature") != NULL)
            {
                head->starSystem.Temperature = atoi(main_attr);
            }
        }

        // head insertion
        // add a star system into linked list
        head->next = starSystemList;
        starSystemList = head;
    }

    // testing output
    /*
    StarSystemListNode *p = head;
    while (p != NULL)
    {
        printf("Testing output( star system )：%s: mass=%lf temp=%d %s %s\n", p->starSystem.Name, p->starSystem.Mass, p->starSystem.Temperature, p->starSystem.Constellation, p->starSystem.Description);
        p = p->next;
    }*/
    
    return starSystemList;
}

/**
 * @brief read explortaion file
 *
 * @param starship_file
 * @param star_system_file
 * @return Exploration
 */
Exploration read_explortaion_file(const char *starship_file, const char *star_system_file)
{
    Exploration exploration;
    exploration.starshipList = read_starship_file(starship_file);
    exploration.starSystemList = read_star_system_file(star_system_file);

    return exploration;
}
